
#ifndef __GLODEF__
#define __GLODEF__ 1

/*
#define NDEBUG
 */

/*
 #define CS_INITIAL_PRESSURE 
 */

#include <math.h>
#include <assert.h>
#include <mpi/mpi.h>

#ifndef __GNUC__
#define __attribute__(T)    
#endif


#define LOG_MPI_WTIME_START     double __wtime__=MPI_Wtime()
#define LOG_MPI_WTIME_STOP      PrintLog("    %s: wall_time = %.3f sec.\n", \
                                    __func__, MPI_Wtime()-__wtime__)

/* some variables needed by MPI.  all these are declared in soah3d.c */
extern int mpi_num_procs, mpi_my_id;
extern int quiet;

#define PRINTF      if((!quiet) && (mpi_my_id==0)) printf
#define FFLUSH      if((!quiet) && (mpi_my_id==0)) fflush

// typedef double FLOAT;
#define SMALLF                  1.0E-16

static const double THIRD = 1.0 / 3.0;

/* field3d is a functional type.
    glo_crds is a pointer to array of 3 global coordinates,
    loc_crds is a pointer to array of 3 local coordinates,
    val points to the value(s) (1 if scalar, array of 3 if vector) of the field
 */
typedef void field3d(double Time, const double *glo_crds, double *val);
typedef void bc_field3d(unsigned on_bdry, double Time, const double *glo_crds, double *val);

#ifdef	__cplusplus
extern "C" {
#endif

/*
__inline__h double fmin(double A, double B){ return (A < B) ? A : B; }
__inline__h double fmax(double A, double B){ return (A > B) ? A : B; }
 */

static inline double sqr(double A) {
    return A * A;
}

static inline double norm(const double A[]) {
    return sqrt(A[0] * A[0] + A[1] * A[1] + A[2] * A[2]);
}

static inline double dist(const double A[], const double B[]) {
    return sqrt(sqr(A[0] - B[0]) + sqr(A[1] - B[1]) + sqr(A[2] - B[2]));
}

static inline double mulvec(const double A[], const double B[]) {
    return A[0] * B[0] + A[1] * B[1] + A[2] * B[2];
}

static inline double crossp(const double A[], const double B[], double P[]) {
    P[0] = A[1] * B[2] - A[2] * B[1];
    P[1] = A[2] * B[0] - A[0] * B[2];
    P[2] = A[0] * B[1] - A[1] * B[0];
    return sqrt(P[0] * P[0] + P[1] * P[1] + P[2] * P[2]);
}

static inline unsigned min(unsigned A, unsigned B) {
    return (A < B) ? A : B;
}

static inline unsigned max(unsigned A, unsigned B) {
    return (A > B) ? A : B;
}

static inline void minmax(int a, int b, int *m, int *M)
{
    register int t = b;
    if (a < b) {
        *m = a;
        *M = t;
    } else {
        *M = a;
        *m = t;
    }
}

#ifdef	__cplusplus
}
#endif



enum {
    FALSE = 0, TRUE = 1
};

/* Target accuracy for linear solvers */
#define LS_ACCURACY             1.0E-12
#define STATSOL_TOL             LS_ACCURACY * 100
#define PERIODIC_TOL            1e-5


#define QGRID_SOLID
// #define QGRID_MEMBRANE


#if defined(QGRID_MEMBRANE) || defined(QGRID_SOLID)
#define USE_QGRID
#else
#undef USE_QGRID
#endif

#ifndef NO_QGRID
#ifndef NEED_GRID_FACES
#define NEED_GRID_FACES     1
#endif
#ifndef NEED_GRID_EDGES
#define NEED_GRID_EDGES     1
#endif
#ifndef NEED_NODES_SORTED
#define NEED_NODES_SORTED   1
#endif
#endif

/*
#define  DEBUG_PRINT_VECS   1
 */
/*
#define  DEBUG_PRINT_MATS   1
 */


#endif

/* TODO: see the list herein
 *      1) fix up all the `ignore = ` and `ignor = ` things
 */
